// Copyright 2020 New Relic, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

using System;
using System.Diagnostics;

namespace NewRelic.Agent.IntegrationTestHelpers.RemoteServiceFixtures;

/// <summary>
/// A remote fixture intended to be run against a console application
/// that runs from begin to end without signaling test framework of it's start
/// </summary>
public class RemoteConsoleApplication : RemoteService
{
    private TimeSpan _timeout = TimeSpan.FromSeconds(60);
    private bool _processHasBeenShutdown;

    protected override bool UsesSpecificPort => false;

    public RemoteConsoleApplication SetTimeout(TimeSpan timeSpan)
    {
        _timeout = timeSpan;
        return this;
    }


    public RemoteConsoleApplication(string applicationDirectoryName, string executableName, ApplicationType applicationType, bool isCoreApp = false, bool publishApp = false)
        : base(applicationDirectoryName, executableName, applicationType, false, isCoreApp, publishApp)
    {
    }

    public RemoteConsoleApplication(string applicationDirectoryName, string executableName, string targetFramework, ApplicationType applicationType, bool isCoreApp = false, bool publishApp = false)
        : base(applicationDirectoryName, executableName, targetFramework, applicationType, false, isCoreApp, publishApp)
    {
    }

    public override void Shutdown(bool force = false)
    {
        if (RemoteProcess is null)
        {
            // We might not have ever started the application, e.g. if the test is being skipped.
            return;
        }
            
        if (_processHasBeenShutdown)
        {
            RemoteProcess.WaitForExit();
            return;
        }

        _processHasBeenShutdown = true;

        try
        {
            if (!IsRunning || RemoteProcess.WaitForExit(Convert.ToInt32(_timeout.TotalMilliseconds)))
            {
                // Allows for any asynchronous writing to complete
                RemoteProcess.WaitForExit();
                return;
            }

            if (IsRunning)
            {
                RemoteProcess.Kill();
            }

            RemoteProcess.WaitForExit();
        }
        catch (Exception ex)
        {
            throw new Exception($"Remote Process \"{_executableName}\" did not complete within the expected duration of {_timeout.TotalSeconds} second(s)", ex);
        }
    }
}
